#pragma once

#include <QTcpServer>
#include <QJsonValue>
#include <QFile>
#include <QMutex>
#include <QTcpSocket>
#include "FileTransferDef.h"

class FileSender_InternalSignals;
class FileSender;

class FileSender : public QObject
{
	Q_OBJECT
protected:
	FileSender(const QString& ip, int port, QObject* parent = nullptr);
	~FileSender();

public:
	QString getId() const;
	void send(const QList<FileTransferDef::sFile>& files);
	void stop();

private slots:
	void onSignalSend(const QList<FileTransferDef::sFile>& files);

private:
	QString getLastErrorString(void);
	FileTransferDef::sFile nextFile();

	void setSendState(FileTransferDef::eSendState);
	FileTransferDef::eSendState getSendState();

	void sendNext();
	void sendOnceBuff();

signals:
	void signalSendError(const QString& error);
	void signalSendChanged(const FileTransferDef::sFile &file);
	void signalSendFinished(const FileTransferDef::sFile &file);
	void signalSendPrograss(qreal percentage);
	void signalSendAllFinished();
	void signalClose();

private slots:
	void onSocketError();
	void onSocketConnected();
	void onMessageReceived();
	void onFileOpenError();

private:
	QTcpSocket* mFileSocket = nullptr;

	QString			mIP;
	int				mPort;
	QString			mErrorString;
	QString			mId;

	FileTransferDef::sFile			mCurrentInternalFile;
	QFile			mCurrentFile;
	qint64			mOnceSendSize = 1024 * 1024 * 50;
	int			m_percentage = 0;

	QList<FileTransferDef::sFile> mFiles;
	qint64 mTotalSize = 0;
	qint64 mFinishedSize = 0;
	FileSender_InternalSignals* mInternalSignals;
	QMutex mFilesLock;
	FileTransferDef::eSendState mSendState = FileTransferDef::eSendState_Running;
	QMutex mSendStateLock;

	friend class HiFileSenderManager;
};

class HiFileSenderManager : public QObject
{
protected:
	HiFileSenderManager();
	~HiFileSenderManager();

public:
	static HiFileSenderManager* getInstance();

public:
	FileSender* createSender(const QString& ip, int port);
	void destroySender(FileSender*);
	QMap<QString, FileSender*> getAllSenders();
	QMap<QString, FileSender*>::const_iterator getAllSendersBeginIterator();

private:
	QMap<QString, FileSender*> mIdAndSenderMap;
	QMap<FileSender*, QThread*> mSenderAndThreadMap;
	static QMutex mLock;
	static HiFileSenderManager* mInstance;
};
HiFileSenderManager* getFileSenderManager();

class FileSender_InternalSignals : public QObject
{
	Q_OBJECT
protected:
	FileSender_InternalSignals(QObject* parent = nullptr) : QObject(parent) {}
	~FileSender_InternalSignals() {}

signals:
	void signalSend(const QList<FileTransferDef::sFile>& files);

	friend class FileSender;
};